﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;

namespace InfiniTec.Configuration
{
	public abstract class ConfigurationElementCollection<TElement, TKey>: ConfigurationElementCollection, IEnumerable<TElement>
		where TElement: ConfigurationElement, new()
	{
		public IEqualityComparer<TKey> KeyComparer { get; set; }

		protected ConfigurationElementCollection()
		{
			KeyComparer = EqualityComparer<TKey>.Default;
		}

		protected ConfigurationElementCollection(IEqualityComparer<TKey> keyComparer)
		{
			KeyComparer = keyComparer;
		}

		public new IEnumerator<TElement> GetEnumerator()
		{
			for (int i = 0; i < Count; i++)
			{
				yield return (TElement) BaseGet(i);
			}
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		protected sealed override object GetElementKey(ConfigurationElement element)
		{
			return GetElementKey((TElement) element);
		}

		protected override ConfigurationElement CreateNewElement()
		{
			return new TElement();
		}

		public void Add(TElement element)
		{
			if (element == null) throw new ArgumentNullException("element");
			BaseAdd(element);
		}

		public void Remove(TElement element)
		{
			if (element == null) throw new ArgumentNullException("element");
			BaseRemove(GetElementKey(element));
		}

		public bool TryGet(TKey key, out TElement result)
		{
			foreach (var element in this)
			{
				if (KeyComparer.Equals(key, GetElementKey(element)))
				{
					result = element;
					return true;
				}
			}
			result = default(TElement);
			return false;
		}

		public void Remove(TKey key)
		{
			TElement item;
			if (!TryGet(key, out item)) return;

			Remove(item);
		}


		protected abstract TKey GetElementKey(TElement configurationElement);
	}
}
